/**
 *	The NeuroCoSA Toolkit
 *	Copyright (C) 2003-6 Stuart Meikle.
 *
 *	This is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation; either
 *	version 2.1 of the License, or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Lesser General Public License for more details.
 *
 * @author	Stuart Meikle
 * @version	2006-halloween(mk2)
 * @license	LGPL
 */
package org.stumeikle.NeuroCoSA;

// demo user classes
import java.util.*;
import java.lang.*;
import org.stumeikle.NeuroCoSA.Brain;
import org.stumeikle.NeuroCoSA.DPU;
import org.stumeikle.NeuroCoSA.DataBlock;
import org.stumeikle.NeuroCoSA.Cortex;
import org.stumeikle.NeuroCoSA.SimpleLayer;
import org.stumeikle.NeuroCoSA.SimpleNeuron;
import org.stumeikle.NeuroCoSA.CortexInfoService;
import org.stumeikle.NeuroCoSA.NIS.*;
import org.stumeikle.NeuroCoSA.AutoClusterSimpleNeuron;
import org.stumeikle.NeuroCoSA.AutoCluster.AutoClusterMemoryControl;
import org.stumeikle.NeuroCoSA.AutoCluster.AutoClusterMemory;
import org.stumeikle.NeuroCoSA.AutoCluster.AutoClusterNeuroCoSAIF;
import org.stumeikle.NeuroCoSA.AutoCluster.NMeasurable;

/**
 * A generic debug layer. User to define how neurons switch on and respond to inputs
 * Assume i think that inputs in this case will be a single double representing a 1d 
 * domain position. 
 * changing this today 20071020 to respond to inputs coming directly from within 
 * -> its something of a hassle to take inputs via the Cortex as these need to be 
 * wrapped in DPUs
 */
public class SimpleDebugLayer extends SimpleLayer
{
    Info			iIncomingSignal;	 
				//store again locally -> in general we'll transform the data
    InfoDoubleWithSingleStore	iWinningLearn;
    LinkedList<NMeasurable>	iInputs;
    ListIterator		iInputIt;
    String			iName;
    static int			iCount=0;

    public SimpleDebugLayer(Cortex l)
    {
	super(l);

	//store the things we need in the info service.
	//maintain a link to them here too
	iIncomingSignal = new Info("IncomingSignal");
	getInfoService().addPublication(iIncomingSignal);
	iName = new String("SimpleDebugLayer" + iCount++);
    }

    public void setInputs(LinkedList<NMeasurable> i)
    {
	iInputs = i;
	iInputIt = iInputs.listIterator();
    }


    public void	setName( String s )
    { iName = s; }

    public void getReady()
    {
	//set the defaults. 
	getInfoService().findInfoString("LayerName").setValue(iName);

System.out.println("MapLayer debug: running get ready for layer = " + iName );
	
	//add in the publication which contains the nput from the world
	//20071020 no longer needed. we'll generate the data in other ways

	//also add the winning learn 
	iWinningLearn = (InfoDoubleWithSingleStore) getInfoService().findInfo("WinningLearnSigStr");
    }

    public void update()
    {
	//get the input from the brain to the lobe from the lobe info service.
	//but how do we get the data there in the first place ? 
	
	//(1)
	//check that we have something useful in the CIS. 
	
	//(2)
	//pass the data to all of the neurons. 
	//20071020 more simple now
	if (iInputIt != null)
	{
	    if (iInputIt.hasNext())
	    {
		NMeasurable	n = (NMeasurable) iInputIt.next();
		iIncomingSignal.setValue(n);
	    }
	    else
	    {
		//reset to the beginning
		iInputIt = iInputs.listIterator();
	    }
	}
	else
	    iIncomingSignal.setValue(null);

	//(3) update the neurons
	updateNeurons();	

	//(4) create any new instances if no neurons are firing
	addNewSimpleDebugNeuron();

	//(5) create any return value if we need to 
    }

    void	addNewSimpleDebugNeuron()
    {
	//check to see if any neuron responded to the noise.
	//we need the actual current value and not the synchronized value
	double	d= iWinningLearn.getDoubleValue(Info.now);

System.out.println("Winning learn signal =" + d);

	if (d<SimpleDebugNeuron.iNeuronSeparationThreshold && iIncomingSignal.getValue()!=null)
	{
	    //nothing fired above the threshold
	    
	    //add a new neuron to represent the sound
	    SimpleDebugNeuron	nn = new SimpleDebugNeuron( this );
	    NMeasurable		nm = (NMeasurable)iIncomingSignal.getValue();

	    nn.setExemplar(nm);	//read in the data from the cis
	    addNeuron(nn);   
	    nn.update();//?
	}
    }
}

